/*
 * CloudBank Mobile Knowledge Sharing for Language Learners
 * Supported by the JISC Rapid Innovation Programme #jiscri
 *
 * Copyright (C) 2010 University of Brighton
 *
 * Licensed under the GNU General Public License v3 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.gnu.org/licenses/gpl.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package uk.ac.brighton.itrg.cloudbank;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.net.Uri;
import android.os.Environment;


public class Media
{
	private static final String TAG = Media.class.getSimpleName();

	
	// note these values are used throughout the client and server.
	// changing them without changing the server will break the application!
	private static final String IMAGE = "image"; 
	private static final String AUDIO = "audio"; 
	
	
	// these are the media files for the *current entry*.
	// (junk if current entry has no media)
	private static File tmp_image;
	private static File tmp_audio;

	
	// --------------------------------------------------------------------------
    // Image and Sound intents need existing, writable, temporary files on the SD 
    // card to store data. We create these files here if not present, and expose 
	// them via getTmpImageURI() and getTmpAudioURI() respectively.
    // SD card is assumed to be present.
	// --------------------------------------------------------------------------
    public static void init() throws Exception
    {
        Logger.log(TAG + ".init()");

		File media_folder = new File(Environment.getExternalStorageDirectory(), Media.class.getName());
		media_folder.mkdirs();

		tmp_image = new File(media_folder, IMAGE + ".jpg");
		tmp_audio = new File(media_folder, AUDIO + ".3gpp"); 

		
		// does not seem logical to create a file first and then ask if we can write, 
		// but other way round file.canWrite() returns false for non-existing files.
		
		tmp_image.createNewFile();
		tmp_audio.createNewFile();			

		if(!tmp_image.canWrite() || !tmp_audio.canWrite())
		{
    		throw new Exception("Cannot write to media tmp files.");
		}
    }
 
   
    public static final File getTmpImageFile()	{return tmp_image;}
    public static final File getTmpAudioFile()	{return tmp_audio;}
    
    public static final String getTmpImageMime(){return ext2mime(file2ext(tmp_image));}
    public static final String getTmpAudioMime(){return ext2mime(file2ext(tmp_audio));}
    
    public static final Uri getTmpImageUri()	{return Uri.fromFile(tmp_image);}    
    public static final Uri getTmpAudioUri()	{return Uri.fromFile(tmp_audio);}


    
	// ------------------------------------------
    // get image or a scaled version of it
	// ------------------------------------------
    public static final Bitmap getTmpImage()
    {
    	return BitmapFactory.decodeFile(tmp_image.getAbsolutePath());
    }
    public static final Bitmap getTmpImage(int canvasWidth, int canvasHeight)
    {
    	Bitmap b1 = BitmapFactory.decodeFile(tmp_image.getAbsolutePath());
    	
    	if(b1 != null)
    	{
            int w = b1.getWidth();
        	int h = b1.getHeight();
        	
        	double ratio = Math.min((double)canvasWidth/w, (double)canvasHeight/h);
            w = (int)(w * ratio);
            h = (int)(h * ratio);

        	Bitmap b2 = Bitmap.createScaledBitmap(b1, w, h, false);
        	
            Bitmap b3 = Bitmap.createBitmap(canvasWidth, canvasHeight, Bitmap.Config.ARGB_8888);
            Canvas c = new Canvas(b3);
            c.drawBitmap(b2, (canvasWidth-w)/2, (canvasHeight-h)/2, null);
            
            return b3; 
    	}
    	
    	return null;
    }
    
    
	// ------------------------------------------
    // retrieve audio recording from location on phone
	// ------------------------------------------
	public static final boolean retrieveAudioFromPhone(String absolutePath)
	{
        Logger.log(TAG + ".retrieveAudioFromPhone(" + absolutePath + ")");

        fix_audio_extension(absolutePath);       
		try 
		{
			InputStream is = new FileInputStream(absolutePath);
			return storeDataFromStream(is, tmp_audio);
		}
		catch (Exception e) 
		{
		    Logger.log(e);
		}
		return false;
	}

    
	// ------------------------------------------
    // get audio from server 
	// ------------------------------------------
	public static final boolean retrieveAudioFromServer(String relativePath)
	{
        fix_audio_extension(relativePath);
        return retrieve(relativePath, tmp_audio);
	}
    
    
    
	// ------------------------------------------
    // get image from server 
	// ------------------------------------------
	public static final boolean retrieveImageFromServer(String relativePath)
	{
        fix_image_extension(relativePath);
		return retrieve(relativePath, tmp_image);
	}

	
	
	// ------------------------------------------
    // get file from server, store in path 
	// ------------------------------------------
	private static final boolean retrieve(String serverPath, File target)
	{
		boolean rc = false;
		
        Logger.log(TAG + ".retrieve(" + serverPath + ", " + target.getAbsolutePath() + ")");

		try
		{
			URL url = new URL(CB.getHost() + serverPath);
			InputStream is = url.openStream();
			return storeDataFromStream(is, target);
		}
		catch(Exception e)
		{
			Logger.log(e);
		}
		
		return rc;
	}
	
	
	
	// ------------------------------------------
    // read data from InputStream, store to path 
	// ------------------------------------------
	private static final boolean storeDataFromStream(InputStream is, File target)
	{
        Logger.log(TAG + ".storeDataFromStream()");

        OutputStream os = null;
		boolean rc = false;
		
		try 
		{
			os = new FileOutputStream(target);
			CB.streamCopy(is, os);
			is.close();
			os.close();
			rc = true;
		} 
		catch (Exception e) 
		{
        	if(is!=null) try {is.close();} catch(Exception ex){}
        	if(os!=null) try {os.close();} catch(Exception ex){}
		    Logger.log(e);
		}
		return rc;
	}
	

	// ------------------------------------------
    // make sure tmp_image has correct extension  
	// HTC=.jpg / Pulse=.jpg / Web=.jpg .png ...
	// ------------------------------------------
	private static void fix_image_extension(String s)
	{
        Logger.log(TAG + ".fix_image_extension(" + s + ")");
        Logger.log("tmp_image", tmp_image.getAbsolutePath());
        
        String ext = str2ext(s);
        if(ext.length() > 0 && !ext.equalsIgnoreCase(file2ext(tmp_image)))
        {
			tmp_image = new File(tmp_image.getParentFile(), IMAGE + ext);
        }

		Logger.log("tmp_image", tmp_image.getAbsolutePath());
	}


	// ------------------------------------------
    // make sure tmp_audio has correct extension  
	// HTC=.3gp / Pulse=.amr / Web=.wav .mp3 ...
	// ------------------------------------------
	private static void fix_audio_extension(String s)
	{
        Logger.log(TAG + ".fix_audio_extension(" + s + ")");
        Logger.log("tmp_audio", tmp_audio.getAbsolutePath());
        
        String ext = str2ext(s);
        if(ext.length() > 0 && !ext.equalsIgnoreCase(file2ext(tmp_audio)))
        {
			tmp_audio = new File(tmp_audio.getParentFile(), AUDIO + ext);
        }

		Logger.log("tmp_audio", tmp_audio.getAbsolutePath());
	}

	
	// ------------------------------------------
	// utility: file extension from file
	// ------------------------------------------
    private static final String file2ext(File f)
    {
    	return str2ext(f.getName());
    }

	// ------------------------------------------
	// utility: file extension from string
	// ------------------------------------------
    private static final String str2ext(String name)
    {
    	String ext = "";
    	
		int dot = name.lastIndexOf(".");
		if(dot > 0)
		{
			ext = name.substring(dot);
		}
		
		return ext;
    }

    
	// ------------------------------------------
	// utility: mime type from file extension
	// ------------------------------------------
    private static final String ext2mime(String ext)
	{
		String mime = "application/octet-stream";
		     if(ext.equals(".jpg"))  mime = "image/jpeg";
		else if(ext.equals(".jpeg")) mime = "image/jpeg";
		else if(ext.equals(".png"))  mime = "image/png";
		else if(ext.equals(".gif"))  mime = "image/gif";
		else if(ext.equals(".bmp"))  mime = "image/bmp";
		else if(ext.equals(".3gpp")) mime = "audio/3gpp";
		else if(ext.equals(".3gp"))  mime = "audio/3gpp";
		else if(ext.equals(".amr"))  mime = "audio/amr";
		else if(ext.equals(".wav"))  mime = "audio/wav";
		else if(ext.equals(".mp3"))  mime = "audio/mpeg";
		
		return mime;
	}
	
}
